import sys
import pygame
from time import sleep

from settings import Settings
from libs.game_stats import GameStats
from libs.button import Button
from libs.my_plane import MyPlane
from libs.bullet import Bullet
from libs.enemy import Enemy


class Game:
    def __init__(self):
        """初始化游戏并创建游戏资源"""
        pygame.init()
        self.clock = pygame.time.Clock()
        self.settings = Settings()
        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height)
        )
        self.settings.screen_width = self.screen.get_rect().width
        self.settings.screen_height = self.screen.get_rect().height
        pygame.display.set_caption("我的第一个游戏")

        # 创建一个用于存储游戏统计信息的实例
        self.stats = GameStats(self)
        self.my_plane = MyPlane(self)
        self.bullets = pygame.sprite.Group()
        self.enemys = pygame.sprite.Group()

        self._create_fleet()

        # 游戏启动后处于非活动状态
        self.game_active = False
        # 创建按钮
        self.play_button = Button(self, "开始游戏")

    def run_game(self):
        """开始游戏主循环"""
        self.background = pygame.Surface(self.screen.get_size())
        self.background = self.background.convert()  # 转换Surface以提高性能
        self.background.fill(self.settings.bg_color)  # 填充背景颜色（可选）
        self.background_image = pygame.image.load("images/bg.png")
        self.background.blit(self.background_image, (0, 0))
        while True:
            # 监听键鼠
            self._check_events()

            if self.game_active:
                self.my_plane.update()
                self._update_bullets()
                self._update_enemys()
            # 每次循环都重绘屏幕
            self._update_screen()
            # 游戏帧率
            self.clock.tick(60)

    def _check_events(self):
        """响应键鼠"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            # 监听鼠标
            if event.type == pygame.MOUSEBUTTONDOWN:
                self._check_mousedown_events(event)

                # 鼠标点击位置
                mouse_pos = pygame.mouse.get_pos()
                self._check_play_button(mouse_pos)

            if event.type == pygame.KEYDOWN:
                self._check_keydown_events(event)
            if event.type == pygame.KEYUP:
                self._check_keyup_events(event)

    def _check_keydown_events(self, event):
        """响应按下事件"""
        if event.key == pygame.K_RIGHT:
            # 开始向右移动
            self.my_plane.moving_right = True
        if event.key == pygame.K_LEFT:
            # 开始向左移动
            self.my_plane.moving_left = True
        if event.key == pygame.K_ESCAPE:
            sys.exit()
        if event.key == pygame.K_SPACE:
            self._fire_bullet()

    def _check_keyup_events(self, event):
        """响应释放事件"""
        if event.key == pygame.K_RIGHT:
            # 停止向右移动
            self.my_plane.moving_right = False
        if event.key == pygame.K_LEFT:
            # 停止向左移动
            self.my_plane.moving_left = False

    def _check_mousedown_events(self, event):
        """响应鼠标按下事件"""
        if event.button == 1:
            self._fire_bullet()

    def _check_play_button(self, mouse_pos):
        """检查是否点击play按钮"""
        button_clicked = self.play_button.rect.collidepoint(mouse_pos)
        if button_clicked and not self.game_active:
            # 重置游戏的统计信息
            self.stats.reset_stats()
            self.game_active = True

            # 清空子弹和敌人
            self.bullets.empty()
            self.enemys.empty()

            # 创建一个新的舰队,放在屏幕底部中央
            self._create_fleet()
            self.my_plane.center_my_plane()

            # 开始游戏后隐藏鼠标
            pygame.mouse.set_visible(False)

    def _fire_bullet(self):
        """创建一颗子弹，并加入编组"""
        if len(self.bullets) < self.settings.bullet_allowed:
            new_bullet = Bullet(self)
            self.bullets.add(new_bullet)

    def _update_bullets(self):
        self.bullets.update()
        # 删除已经消失的子弹
        for bullet in self.bullets.copy():
            if bullet.rect.bottom <= 0:
                self.bullets.remove(bullet)
        self._check_bullet_enemy_collisions()

    def _check_bullet_enemy_collisions(self):
        # 检查是否有子弹击中了敌人
        collisions = pygame.sprite.groupcollide(self.bullets, self.enemys, False, True)

        if not self.enemys:
            # 删除现有的子弹并创建一个新舰队
            self.bullets.empty()
            self._create_fleet()

    def _create_fleet(self):
        """创建敌人舰队"""

        # 创建一个敌人，再不断添加，直到没有空间添加新的为止
        # 敌人的间距为敌人的宽度和高度
        enemy = Enemy(self)
        enemy_width, enemy_height = enemy.rect.size

        current_x, current_y = enemy_width, enemy_height
        while current_y < (self.settings.screen_height - 20 * enemy_height):
            while current_x < (self.settings.screen_width - 2 * enemy_width):
                self._create_enemy(current_x, current_y)
                current_x += 2 * enemy_width

            # 添加一行敌人后，重置x值并递增y值
            current_x = enemy_width
            current_y += 2 * enemy_height

    def _create_enemy(self, x_position, y_position):
        """创建一个敌人并将其放在舰队中"""
        new_enemy = Enemy(self)
        new_enemy.x = x_position
        new_enemy.rect.x = x_position
        new_enemy.rect.y = y_position
        self.enemys.add(new_enemy)

    def _check_fleet_edges(self):
        """在有敌人到达边缘时采取相应的措施"""
        for enemy in self.enemys.sprites():
            if enemy.check_edges():
                self._change_fleet_direction()
                break

    def _check_enemys_bottom(self):
        """检查是否有敌人到达了屏幕的下边缘"""
        for enemy in self.enemys.sprites():
            if enemy.rect.bottom >= self.settings.screen_height:
                self._my_plane_hit()
                break

    def _change_fleet_direction(self):
        """将整个舰队向下移动并改变他们的方向"""
        for enemy in self.enemys.sprites():
            enemy.rect.y += self.settings.fleet_drop_speed
        self.settings.fleet_direction *= -1

    def _update_enemys(self):
        """检测是否有敌人位于屏幕边缘，并更新敌人位置"""
        self._check_fleet_edges()
        self.enemys.update()
        # 检测敌人和飞机间的碰撞
        if pygame.sprite.spritecollideany(self.my_plane, self.enemys):
            self._my_plane_hit()
        self._check_enemys_bottom()

    def _my_plane_hit(self):
        """响应飞机和敌人的碰撞"""
        if self.stats.life > 0:
            # 命-1
            self.stats.life -= 1

            # 清空子弹和敌人
            self.bullets.empty()
            self.enemys.empty()

            # 创建一个新的舰队,放在屏幕底部中央
            self._create_fleet()
            self.my_plane.center_my_plane()

            # 暂停
            sleep(0.5)
        else:
            self.game_active = False
            # 结束游戏后显示鼠标
            pygame.mouse.set_visible(True)

    def _update_screen(self):
        """更新屏幕上的图像，并切换到新屏幕"""
        self.screen.fill(self.settings.bg_color)
        # 在屏幕上平铺背景图片
        for x in range(
            0, self.settings.screen_width, self.background_image.get_width()
        ):
            for y in range(
                0, self.settings.screen_height, self.background_image.get_height()
            ):
                self.screen.blit(self.background, (x, y))

        # 绘制子弹
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()
        self.my_plane.blitme()
        self.enemys.draw(self.screen)

        # 如果游戏处于非活动状态，就绘制开始按钮
        if not self.game_active:
            self.play_button.draw_button()

        # 让最近绘制的屏幕可见
        pygame.display.flip()


if __name__ == "__main__":
    # 创建游戏实例并运行游戏
    gm = Game()
    gm.run_game()
